package common.fengkai.filepost.aspect;

import com.alibaba.fastjson.JSONObject;
import common.fengkai.filepost.annotation.LogAnnotation;
import common.fengkai.filepost.bean.mysqlBean.RequestLogEntity;
import common.fengkai.filepost.common.interfaces.Convert;
import common.fengkai.filepost.dao.mysqldao.RequestLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author Fengkai
 * @creat 2022/11/22
 */
@Aspect
@Component
@Slf4j
public class LogAspect {


    @Resource
    private RequestLogMapper requestLogMapper;


    /**
     * 定义切点
     */
    @Pointcut("@annotation(common.fengkai.filepost.annotation.LogAnnotation)")
    public void logSave(){};

    //定义一个线程池
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(200));


    /**
     * 织入 记录日志
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("logSave()")
    public Object checkAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //获取入参信息
        Object proceed = proceedingJoinPoint.proceed();

        //获取请求信息
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        threadPoolExecutor.execute( () -> {
            String ip = request.getRemoteAddr();
            String requestURI = request.getRequestURI();
            //通过切点获取入参
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();

            //通过反射拿到注解上的描述信息和转换出来的实体类
            LogAnnotation annotation = signature.getMethod().getAnnotation(LogAnnotation.class);
            Class<? extends Convert> convter = annotation.convter();
            try {
                Convert convert = convter.newInstance();
                RequestLogEntity requestLogEntity = convert.convert(proceedingJoinPoint.getArgs()[0]);
                requestLogEntity.setRequestDesc(annotation.desc()[0]);
                requestLogEntity.setRequestIp(ip);
                requestLogEntity.setRequestUrl(requestURI);
                requestLogMapper.insert(requestLogEntity);
                log.info("请求信息,{}", JSONObject.toJSONString(requestLogEntity));
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });

        return proceed;
    }
}
